﻿using Microsoft.Extensions.Options;

namespace Xms.Abp;

public class DialogService
{
    public DialogService(DrawerService drawerService, ModalService modalService, IOptions<ThemeSettings> options)
    {
        DrawerService = drawerService;
        ModalService = modalService;
        Options = options;
    }
    public DrawerService DrawerService { get; set; }
    public ModalService ModalService { get; set; }
    public IOptions<ThemeSettings> Options { get; set; }
    public async Task OpenAsync<TView>(string title, bool closable = true, bool maskClosable = true, int? width = null)
        where TView : FeedbackComponent<string, string>
    {
        await OpenAsync<TView, string, string>(title, null, closable, maskClosable, width);
    }
    public async Task OpenAsync<TView, TParameter>(string title, TParameter parameter, bool closable = true, bool maskClosable = true, int? width = null)
        where TView : FeedbackComponent<TParameter, string>
    {
        await OpenAsync<TView, TParameter, string>(title, parameter, closable, maskClosable, width);
    }
    public async Task<TResult> OpenAsync<TView, TResult>(string title, bool closable = true, bool maskClosable = true, int? width = null)
        where TView : FeedbackComponent<string, TResult>
    {
        return await OpenAsync<TView, string, TResult>(title, null, closable, maskClosable, width);
    }
    public async Task<TResult> OpenAsync<TView, TParameter, TResult>(string title, TParameter parameter, bool closable = true, bool maskClosable = true, int? width = null)
        where TView : FeedbackComponent<TParameter, TResult>
    {
        if (Options.Value.DialogMode == ShowDialogMode.Drawer)
        {
            return await DrawerService.CreateDialogAsync<TView, TParameter, TResult>(parameter, closable, maskClosable, title, width ?? Options.Value.DialogWidth);
        }
        else
        {
            var options = new ModalOptions
            {
                MaskClosable = maskClosable,
                Width = width ?? Options.Value.DialogWidth,
                Closable = closable,
                Title = title,
            };

            var taskCompletionSource = new TaskCompletionSource<TResult>();
            var modalRef = await ModalService.CreateModalAsync<TView, TParameter, TResult>(options, parameter);
            modalRef.OnCancel = async r =>
            {
                taskCompletionSource.SetResult(r);
                await Task.CompletedTask;
            };
            modalRef.OnClose = async () =>
            {
                taskCompletionSource.SetResult(default);
                await Task.CompletedTask;
            };
            modalRef.OnOk = async r =>
            {
                taskCompletionSource.SetResult(r);
                await Task.CompletedTask;
            };
            return await taskCompletionSource.Task;
        }
    }

    private async Task<bool> CreateDialogAsync<TView, TKey>(DialogAction dialogAction, string title, TKey id, object obj = null, int? width = null)
        where TView : DetailsViewBase<TKey>
    {
        if (Options.Value.DialogMode == ShowDialogMode.Drawer)
        {
            return await DrawerService.CreateDialogAsync<TView, (DialogAction, TKey, object), bool>((dialogAction, id, obj), dialogAction == DialogAction.Details, dialogAction == DialogAction.Details, title: title, width: width ?? Options.Value.DialogWidth);
        }
        else
        {
            var options = new ModalOptions
            {
                MaskClosable = dialogAction == DialogAction.Details,
                Width = width ?? Options.Value.DialogWidth,
                Closable = dialogAction == DialogAction.Details,
                Title = title,
            };

            var taskCompletionSource = new TaskCompletionSource();
            var modalRef = await ModalService.CreateModalAsync<TView, (DialogAction, TKey, object), bool>(options, (dialogAction, id, obj));
            var result = false;
            modalRef.OnCancel = async r =>
            {
                taskCompletionSource.SetResult();
                result = false;
                await Task.CompletedTask;
            };
            modalRef.OnOk = async r =>
            {
                taskCompletionSource.SetResult();
                result = true;
                await Task.CompletedTask;
            };
            await taskCompletionSource.Task;
            return result;
        }
    }
    public async Task OpenDetailsAsync<TView>(string title, Guid id, object obj = null, int? width = null)
        where TView : DetailsViewBase<Guid>
    {
        await OpenDetailsAsync<TView, Guid>(title, id, obj, width);
    }
    public async Task<bool> OpenCreateAsync<TView>(string title, Guid parentId = default, object obj = null, int? width = null)
        where TView : DetailsViewBase<Guid>
    {
        return await OpenCreateAsync<TView, Guid>(title, parentId, obj, width);
    }
    public async Task<bool> OpenUpdateAsync<TView>(string title, Guid id, object obj = null, int? width = null)
        where TView : DetailsViewBase<Guid>
    {
        return await OpenUpdateAsync<TView, Guid>(title, id, obj, width);
    }
    public async Task<bool> OpenReviewAsync<TView>(string title, Guid id, object obj = null, int? width = null)
        where TView : DetailsViewBase<Guid>
    {
        return await OpenReviewAsync<TView, Guid>(title, id, obj, width);
    }

    public async Task OpenDetailsAsync<TView, TKey>(string title, TKey id, object obj = null, int? width = null)
        where TView : DetailsViewBase<TKey>
    {
        await CreateDialogAsync<TView, TKey>(DialogAction.Details, title, id, obj, width);
    }
    public async Task<bool> OpenCreateAsync<TView, TKey>(string title, TKey parentId = default, object obj = null, int? width = null)
        where TView : DetailsViewBase<TKey>
    {
        return await CreateDialogAsync<TView, TKey>(DialogAction.Create, title, parentId, obj, width);
    }
    public async Task<bool> OpenUpdateAsync<TView, TKey>(string title, TKey id, object obj = null, int? width = null)
        where TView : DetailsViewBase<TKey>
    {
        return await CreateDialogAsync<TView, TKey>(DialogAction.Update, title, id, obj, width);
    }
    public async Task<bool> OpenReviewAsync<TView, TKey>(string title, TKey id, object obj = null, int? width = null)
        where TView : DetailsViewBase<TKey>
    {
        return await CreateDialogAsync<TView, TKey>(DialogAction.Review, title, id, obj, width);
    }
}
